package com.jl;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.data.redis.support.atomic.RedisAtomicLong;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * redis工具类
 *
 * @param <T>
 */
@Component
public class JLRedisTemplate<T> {

    @Resource
    private RedisTemplate<String, T> redisTemplate;

    /**
     * 写入
     *
     * @param key
     * @param value
     */
    public void set(String key, T value) {
        redisTemplate.opsForValue().set(key, value);
    }

    /**
     * 写入
     *
     * @param key
     * @param value
     * @param time  秒
     */
    public void set(String key, T value, long time) {
        ValueOperations<String, T> operations = redisTemplate.opsForValue();
        operations.set(key, value);
        redisTemplate.expire(key, time, TimeUnit.SECONDS);
    }

    /**
     * 写入
     *
     * @param map
     */
    public void set(Map<String, T> map) {
        redisTemplate.opsForValue().multiSet(map);
    }

    /**
     * 获取
     *
     * @param key
     * @return
     */
    public T get(String key) {
        return redisTemplate.opsForValue().get(key);
    }

    /**
     * 获取
     *
     * @param keys
     * @return
     */
    public List<T> get(List<String> keys) {
        return redisTemplate.opsForValue().multiGet(keys);
    }

    /**
     * 删除
     *
     * @param key
     */
    public void del(String key) {
        redisTemplate.delete(key);
    }

    /**
     * 删除
     *
     * @param keys
     */
    public void del(List<String> keys) {
        redisTemplate.delete(keys);
    }

    /**
     * 是否存在
     *
     * @param key
     * @return
     */
    public boolean exists(String key) {
        return redisTemplate.hasKey(key);
    }

    /**
     * 列表写入元素（左）
     *
     * @param key
     * @param value
     */
    public void setLeftList(String key, T value) {
        redisTemplate.opsForList().leftPush(key, value);
    }

    /**
     * 列表写入元素（右）
     *
     * @param key
     * @param value
     */
    public void setRightList(String key, T value) {
        redisTemplate.opsForList().rightPush(key, value);
    }

    /**
     * 列表获取元素（左）
     *
     * @param key
     * @param start 下标 0为第一个
     * @param end
     * @return
     */
    public List<T> getLeftList(String key, long start, long end) {
        return redisTemplate.opsForList().range(key, start, end);
    }

    /**
     * 列表获取元素（右）
     *
     * @param key
     * @param start 下标 0为第一个
     * @param end
     * @return
     */
    public List<T> getRightList(String key, long start, long end) {
        return redisTemplate.opsForList().range(key, (end + 1) * -1, (start + 1) * -1);
    }

    /**
     * 列表移除最前一个元素并返回（左）
     *
     * @param key
     * @return
     */
    public T getLpopList(String key) {
        return redisTemplate.opsForList().leftPop(key);
    }

    /**
     * 列表移除最后一个元素并返回（右）
     *
     * @param key
     * @return
     */
    public T getRpopList(String key) {
        return redisTemplate.opsForList().rightPop(key);
    }

    /**
     * 列表元素长度
     *
     * @param key
     * @return
     */
    public Long getListSize(String key) {
        return redisTemplate.opsForList().size(key);
    }

    /**
     * 修改列表元素
     *
     * @param key
     * @param index
     * @param value
     */
    public void updateList(String key, long index, T value) {
        redisTemplate.opsForList().set(key, index, value);
    }

    /**
     * 删除列表元素
     *
     * @param key
     * @param value
     */
    public void delList(String key, T value) {
        redisTemplate.opsForList().remove(key, 0, value);
    }

    /**
     * 原子变量自增
     *
     * @param key
     */
    public long setAtomicIn(String key) {
        return new RedisAtomicLong(key, redisTemplate.getConnectionFactory()).getAndIncrement();
    }

    /**
     * 原子变量自减
     *
     * @param key
     */
    public long setAtomicId(String key) {
        return new RedisAtomicLong(key, redisTemplate.getConnectionFactory()).getAndDecrement();
    }

    /**
     * 获取原子变量
     *
     * @param key
     */
    public long getAtomic(String key) {
        return new RedisAtomicLong(key, redisTemplate.getConnectionFactory()).get();
    }


    @Bean
    public RedisTemplate redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate redisTemplate = new RedisTemplate();
        RedisSerializer stringSerializer = new StringRedisSerializer();
        redisTemplate.setConnectionFactory(factory);
        //设置key编码
        redisTemplate.setKeySerializer(stringSerializer);
        redisTemplate.setHashKeySerializer(stringSerializer);
        //设置value编码
        Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);
        redisTemplate.setDefaultSerializer(serializer);
        //序列化时添加对象信息
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.activateDefaultTyping(objectMapper.getPolymorphicTypeValidator(), ObjectMapper.DefaultTyping.NON_FINAL);
        serializer.setObjectMapper(objectMapper);
        return redisTemplate;
    }

}
